/**
 * Copyright (C), -2025, www.bosssof.com.cn
 * @FileName RoleServiceImpl.java
 * @Author Administrator
 * @Date 2022-9-30  16:25
 * @Description 包含角色管理界面的功能实现
 * History:
 * <author> Administrator
 * <time> 2022-9-30  16:25
 * <version> 1.0.0
 * <desc> abel.zhan 优化代码结构 分配用户方法采用清除用户角色重新分配，优化角色的多资源分配方式 优化代码结构和效率改为批量插入
 */
package com.sd365.permission.centre.service.impl;

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.sd365.common.core.annotation.stuffer.IdGenerator;
import com.sd365.common.core.common.aop.MyPageInfo;
import com.sd365.common.core.common.exception.BusinessException;
import com.sd365.common.core.context.BaseContextHolder;
import com.sd365.common.util.BeanUtil;
import com.sd365.permission.centre.dao.mapper.*;
import com.sd365.permission.centre.entity.*;
import com.sd365.permission.centre.pojo.dto.*;
import com.sd365.permission.centre.pojo.query.RoleQuery;
import com.sd365.permission.centre.pojo.query.UserQuery;
import com.sd365.permission.centre.pojo.vo.*;
import com.sd365.permission.centre.service.RoleService;
import com.sd365.permission.centre.service.exception.UserCentreExceptionCode;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @Class RoleServiceImpl
 * @Author 史旭升
 * @Date 2022-12-24 13:24
 * @version 1.0.0
 */
@Service
@Slf4j
public class RoleServiceImpl  extends AbstractBaseDataServiceImpl implements RoleService {

    public static final String ROLE_ID = "roleId";
    public static final String NOTEULL_ID = "id不能为空";
    @Autowired
    private RoleMapper roleMapper;


    @Autowired
    private RoleResourceMapper roleResourceMapper;


    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private IdGenerator idGenerator;

    @Autowired
    private ResourceMapper resourceMapper;

    @Autowired
    private CompanyMapper companyMapper;

    @Autowired
    private DepartmentMapper departmentMapper;

    @Override
    public Boolean initRoleResourceRedis(Role role) {
        return true;
    }

    @Override
    public Boolean assignResource(RoleResourceDTO roleResourceDTO) {
        //断言，参数进行非空判断
        Assert.notNull(roleResourceDTO,"roleResourceDTO不能为空");
        if (null==roleResourceDTO.getRoleIds()&&roleResourceDTO.getRoleIds().isEmpty()) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATAM_SERVICE_OTHER_EXCEPTION_CODE, new Exception("RoleIds不能为空"));
        }
       // 能够实现多对多，获取角色id集合和资源id集合
        List<Long> roleIds = roleResourceDTO.getRoleIds();
        List<Long> resourceIds = roleResourceDTO.getResourceIds();
        for (Long roleId : roleIds) {
            // 调用 roleResourceMapper的delete方法清空对应角色的所有资源信息
            roleResourceMapper.deleteByRoleId(roleId);
            //创建roleResource对象,选择用户
            RoleResource roleResource = new RoleResource();
            super.baseDataStuff4Add(roleResource);
            super.baseDataStuffCommonPros(roleResource);
            roleResource.setRoleId(roleId);
            //逐个用户分配资源
            for (Long resourceId : resourceIds) {
                roleResource.setId(idGenerator.snowflakeId());
                roleResource.setResourceId(resourceId);
                roleResource.setStatus((byte) 0);
                roleResource.setVersion(INITIALIZE_VERSION_VALUE);
                roleResourceMapper.insert(roleResource);
            }
        }
        return true;
    }

    @Override
    public Boolean assignUser(UserRoleDTO userRoleDTO) {
        Assert.isTrue(userRoleDTO!=null,"userRoleDTO不能为空");
        Assert.notEmpty(userRoleDTO.getRoleIds(),"RoleIds不能为空");
        //获取角色id列表和用户id列表
        List<Long> roleIds = userRoleDTO.getRoleIds();
        List<Long> userIds = userRoleDTO.getUserIds();
        for (Long roleId : roleIds) {
            // 删除原来的角色所对用的用户(在userRoleMapper中新增该方法)
            userRoleMapper.deleteAllByRoleID(roleId);
            // 插入角色所包含的新用户
            UserRole userRole = new UserRole();
            super.baseDataStuff4Add(userRole);
            super.baseDataStuffCommonPros(userRole);
            userRole.setRoleId(roleId);
            // 逐个插入
            for (Long userId : userIds) {
                userRole.setId(idGenerator.snowflakeId());
                userRole.setUserId(userId);
                userRole.setStatus(INITIALIZE_STATUS_VALUE);
                userRole.setVersion(INITIALIZE_VERSION_VALUE);
                userRoleMapper.insert(userRole);
            }
        }
        return true;
    }


    @Override
    public List<Node> queryResourceByRoleId(long roleId) {
            return new ArrayList<>();
    }

    @Override
    public List<Node> selectCompany() {
        return roleMapper.selectCompany();
    }

    @Override
    public  boolean haveRole( RoleDTO roleDTO) {
        if (null == roleDTO) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATAM_SERVICE_OTHER_EXCEPTION_CODE, new Exception("roleDTO不能为空"));
        }
        //根据code查询是否重复，
       return roleMapper.haveRole1(roleDTO.getCode()) <= 0;
    }

    /**
     *增加角色
     * @author shi xusheng
     * @date 2022/12/26 12:07
     * @param roleDTO
     * @return java.lang.Boolean
     */
    @Override
    public Boolean add(RoleDTO roleDTO) {
        if (null == roleDTO) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATAM_SERVICE_OTHER_EXCEPTION_CODE, new Exception("roleDTO不能为空"));
        }
        /*code不能重复
        根据code查询是否重复，
        判断是否存在*/
        if(roleMapper.haveRole1(roleDTO.getCode())>0){
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE, new Exception("角色编号不能重复"));
        }else {
            Role role = new Role();
            role.setName(roleDTO.getName());
            role.setCode(roleDTO.getCode());
            role.setStatus(INITIALIZE_STATUS_VALUE);
            role.setVersion(INITIALIZE_VERSION_VALUE);
            //数据填充
            role.setId(idGenerator.snowflakeId());
            super.baseDataStuff4Add(role);
            super.baseDataStuffCommonPros(role);
            //类型转换
            BeanUtil.copy(role, RoleDTO.class);
            return roleMapper.insert(role) > 0;
        }
    }

    @Override
    public Boolean remove(Long id, Long version) {
        if (null == id) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATAM_SERVICE_OTHER_EXCEPTION_CODE, new Exception(NOTEULL_ID));
        }
        //删除basic_role_resource中的数据
        Example exampleRoleResource = new Example(RoleResource.class);
        exampleRoleResource.createCriteria().andEqualTo(ROLE_ID, id);
        roleResourceMapper.deleteByExample(exampleRoleResource);
        //删除basic_user_role中的数据
        Example exampleUserRole = new Example(UserRole.class);
        exampleUserRole.createCriteria().andEqualTo(ROLE_ID, id);
        userRoleMapper.deleteByExample(exampleUserRole);
        //删除basic_role表中的数据，先删除从表再删除主表
         Example exampleRole = new Example(Role.class);
        exampleRole.createCriteria().andEqualTo("id", id).andEqualTo("version", version);
       return roleMapper.deleteByExample(exampleRole) > 0;

    }

    /**
     * @Description: 批量删除角色，要删除和角色关联的表的所有相关数据
     * @Author: shi xusheng
     * @DATE: 2022-12-26  13:24
     * @param: roleDTOS
     * @return: Boolean
     */
    @Override
    public Boolean batchRemove(RoleDTO[] roleDTOS) {
        Assert.notEmpty(roleDTOS, "roleDTOS不为空！");
        //逐个删除
        for (RoleDTO roleDTO : roleDTOS) {
            //id不能为空
            if (roleDTO.getId() == null) {
                throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATAM_SERVICE_OTHER_EXCEPTION_CODE, new Exception(NOTEULL_ID));
            }
            //删除basic_role_resource中的数据
            Example exampleRoleResource = new Example(RoleResource.class);
            exampleRoleResource.createCriteria().andEqualTo(ROLE_ID, roleDTO.getId());
            roleResourceMapper.deleteByExample(exampleRoleResource);
            //删除basic_user_role中的数据
            Example exampleUserRole = new Example(UserRole.class);
            exampleUserRole.createCriteria().andEqualTo(ROLE_ID, roleDTO.getId());
            userRoleMapper.deleteByExample(exampleUserRole);
            //删除basic_role表中的数据，先删除从表再删除主表
            Example example = new Example(Role.class);
            example.createCriteria().andEqualTo("id", roleDTO.getId());
            roleMapper.deleteByExample(example);
        }
        return true;
}

    @Override
    public boolean modify(RoleDTO roleDTO) {
        if (null == roleDTO) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATAM_SERVICE_OTHER_EXCEPTION_CODE, new Exception("参数不能为空"));
    }
        //修改当前选中对象code可以重复，否则code不能重复
        //根据id查询到对应角色，
        Role currentRole = roleMapper.selectById(roleDTO.getId());
        //currentRole不为空且要修改的对象不是当前选中对象（修改了编号）
        if(currentRole != null && !currentRole.getCode().equals(roleDTO.getCode())){
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE, new Exception("角色编号不能重复"));
        }else {
            //数据转换到role 进行修改
            Role role = BeanUtil.copy(roleDTO, Role.class);
            super.baseDataStuff4Updated(role);
            super.baseDataStuffCommonPros(role);
            role.setName(roleDTO.getName());
            role.setCode(roleDTO.getCode());
            //根据id和version查找到对应的数据修改
            Example example = new Example(Role.class);
            example.createCriteria().andEqualTo("id", roleDTO.getId());
            //转换成roleDto返回
            RoleDTO roleDTOBack = BeanUtil.copy(role, RoleDTO.class);
            BeanUtil.copy(role.getCompany(), roleDTOBack.getCompanyDTO(), CompanyDTO.class);
            BeanUtil.copy(role.getOrganization(), roleDTOBack.getOrganizationDTO(), OrganizationDTO.class);
            BeanUtil.copy(role.getTenant(), roleDTOBack.getTenantDTO(), TenantDTO.class);
            return roleMapper.updateByExample(role, example) > 0;
        }
    }


    @Override
    public RoleDTO copy(Long id) {
        if (null == id) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATAM_SERVICE_OTHER_EXCEPTION_CODE, new Exception("参数不能为空"));
        }
        Role role = roleMapper.selectByPrimaryKey(id);
        //转换为roleDto对象返回
        if (role != null) {
            return BeanUtil.copy(role, RoleDTO.class);
        } else {
            return new RoleDTO();
        }
    }


    @Override
    public List<RoleDTO> commonQuery(RoleQuery roleQuery) {
        if (null == roleQuery) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATAM_SERVICE_OTHER_EXCEPTION_CODE, new Exception("roleQuery不能为空"));
    }
        //获取到参数的id和name
        Role role = new Role();
        role.setName(roleQuery.getName());
        role.setCompanyId(roleQuery.getCompanyId());
        //根据id和name查询
        List<Role> roles = roleMapper.commonQuery(role);
        //设置分页参数
        Page<Role> page = (Page) roles;
        BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));
        //转换为roleDto对象返回，调用beanUtil的集合转换方法
        return BeanUtil.copyList(roles, RoleDTO.class,(o,o1) ->{
                Role role1 = (Role) o;
                RoleDTO roleDTO = (RoleDTO) o1;
                BeanUtil.copy(role1.getCompany(), roleDTO.getCompanyDTO(), CompanyDTO.class);
                BeanUtil.copy(role1.getOrganization(), roleDTO.getOrganizationDTO(), OrganizationDTO.class);
                BeanUtil.copy(role1.getTenant(), roleDTO.getTenantDTO(), TenantDTO.class);
                }
        );
    }


    @Override
    public List<UserVO> commonQueryUser(UserQuery userQuery) {
        if (null == userQuery) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATAM_SERVICE_OTHER_EXCEPTION_CODE, new Exception("userQuery参数不能为空"));
        }
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        //根据name查询
        if (userQuery.getName() != null) {
            //模糊查询
            criteria.orLike("name", "%" + userQuery.getName() + "%");
        } else {
            criteria.orLike("name", userQuery.getName());
        }
        List<User> users = userMapper.selectByExample(example);
        //分页参数设置
        Page<User> page = (Page) users;
        BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));
        List<UserDTO> userDTOS = getUserDTOS(users);
        //转换成user返回
         return BeanUtil.copyList(userDTOS, UserVO.class, (o,o1) -> {
                    UserDTO userDTO = (UserDTO) o;
                    UserVO userVO = (UserVO) o1;
                    if (!ObjectUtils.isEmpty(userDTO.getCompany())) {
                        userVO.setCompany(BeanUtil.copy(userDTO.getCompany(), CompanyVO.class));
                    }
                    if (!ObjectUtils.isEmpty(userDTO.getDepartment())) {
                        userVO.setDepartmentVO(BeanUtil.copy(userDTO.getDepartment(), DepartmentVO.class));
                    }

            });
    }
    /**
     *commonQueryUser抽取出来用来完成类型转换
     * @author shi xusheng
     * @date 2023/01/15 00:36
     * @param users
     * @return java.util.List<com.sd365.permission.centre.pojo.dto.UserDTO>
     */
    @Nullable
    public List<UserDTO> getUserDTOS(List<User> users) {
        //转换成UseDTO
        List<UserDTO> userDTOS = BeanUtil.copyList(users, UserDTO.class);
        if (!CollectionUtils.isEmpty(userDTOS)) {
            for (UserDTO userDTO : userDTOS) {
                if (!ObjectUtils.isEmpty(userDTO.getCompanyId())) {
                    //通过id查询company
                    Long companyId = userDTO.getCompanyId();
                    Company company = companyMapper.selectById(companyId);
                    userDTO.setCompany(BeanUtil.copy(company, CompanyDTO.class));
                }
                if (!ObjectUtils.isEmpty(userDTO.getDepartmentId())) {
                    //通过id查询department
                    Long departmentId = userDTO.getDepartmentId();
                    Department department = departmentMapper.getCompany(departmentId);
                    userDTO.setDepartment(BeanUtil.copy(department, DepartmentDTO.class));
                }
            }
        }
        return userDTOS;
    }

    @Override
    public RoleVO  queryById(Long id) {
        if (null == id) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATAM_SERVICE_OTHER_EXCEPTION_CODE, new Exception(NOTEULL_ID));
        }
        //id查询角色
        Role role = roleMapper.selectById(id);
        //对象类型转换
        return BeanUtil.copy( BeanUtil.copy(role, RoleDTO.class), RoleVO.class);
    }


    @Override
    public RoleDTO queryUserResource(Long id) {
        if (null == id) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATAM_SERVICE_OTHER_EXCEPTION_CODE, new Exception(NOTEULL_ID));
        }
        Role role = roleMapper.selectByPrimaryKey(id);
        Example example = new Example(RoleResource.class);
        example.selectProperties("resourceId");
        example.createCriteria().andEqualTo(ROLE_ID, id);
        List<RoleResource> roleResources = roleResourceMapper.selectByExample(example);
        Set<Long> idSet = new HashSet<>();
        for (RoleResource roleResource : roleResources) {
            idSet.add(roleResource.getResourceId());
        }
        if (!idSet.isEmpty()) {
            Example re = new Example(Resource.class);
            re.createCriteria().andIn("id", idSet);
            List<Resource> resources = resourceMapper.selectByExample(re);
            List<ResourceDTO> resourceDTOS = BeanUtil.copyList(resources, ResourceDTO.class);
            RoleDTO copy = BeanUtil.copy(role, RoleDTO.class);
            copy.setResourceDTOS(resourceDTOS);
            return copy;
        } else {
            return null;
        }
    }


    @Override
    public RoleCompanyVO queryRoleCompanyById(Long id) {
        return null;
    }

    @Override
    public Boolean modifyRoleCompany(RoleCompanyDTO roleCompanyDTO) {
        return true;
    }

    @Override
    public RoleVO getCopyRoleVO(RoleDTO roleDTO) {
        if (roleDTO != null) {
            RoleVO copyRoleVO = BeanUtil.copy(roleDTO, RoleVO.class);
            List<ResourceVO> resourceVOS = BeanUtil.copyList(roleDTO.getResourceDTOS(), ResourceVO.class);
            copyRoleVO.setResourceVOS(resourceVOS);
            return copyRoleVO;
        } else {
            return new RoleVO();
        }
    }

}
